package com.gamefx.binding
{
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	
	public dynamic class BindingProxy extends Proxy
	{
		private var _source:*;
		private var propMap:Object;
		private var setterMap:Object;
		
		public function BindingProxy(source:*)
		{
			_source = source;
			propMap = {};
			setterMap = {};
		}
		
		
		override flash_proxy function callProperty(methodName:*, ... args):*
		{
			return _source[methodName].apply(_source, args);
		}
		
		override flash_proxy function getProperty(name:*):*
		{
			return _source[name];
		}
		
		override flash_proxy function setProperty(name:*, value:*):void
		{
			_source[name] = value;
			
			var i:int;
			var map:Array;
			
			if (propMap.hasOwnProperty(name))
			{
				map = propMap[name] as Array;
				for (i=0; i< map.length; i++)
				{
					map[i].target[map[i].prop] = value;
				}
			}
			
			if (setterMap.hasOwnProperty(name))
			{
				map = setterMap[name] as Array;
				for (i=0; i< map.length; i++)
				{
					(map[i] as Function)(value);
				}
			}
		}
		
		override flash_proxy function deleteProperty(name:*):Boolean
		{
			if (_source.hasOwnProperty(name))
			{
				delete _source[name];
				return true;
			}
			else
			{
				return false;
			}
		}
		
		override flash_proxy function hasProperty(name:*):Boolean
		{
			return _source.hasOwnProperty(name);
		}
		
		
		
		
		internal function bindProperty(chain:String, site:Object, prop:String):void
		{
			if (!_source.hasOwnProperty(chain))
			{
				throw new Error("Can't find property:" + chain);
				return;
			}
			
			if (!propMap.hasOwnProperty(chain))
			{
				propMap[chain] = [];
			}
			
			propMap[chain].push({target: site, prop: prop});
			
			site[prop] = _source[chain];
		}
		
		
		internal function bindSetter(chain:String, setter:Function):void
		{
			if (!_source.hasOwnProperty(chain))
			{
				throw new Error("Can't find property:" + chain);
				return;
			}
			
			if (!setterMap.hasOwnProperty(chain))
			{
				setterMap[chain] = [];
			}
			
			setterMap[chain].push(setter);
			
			setter(this[chain]);
		}
	}
}